home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr48 / pasclern.zip / CHAP12.TXT < prev    next >
Text File  |  1993-04-01  |  22KB  |  521 lines

  1.               CHAPTER 12 - Pointers and Dynamic Allocation
  2.  
  3.  
  4.  
  5.             For  certain  types of programs,  pointers  and  dynamic 
  6.         allocation can be a tremendous advantage,  but most programs 
  7.         do not need such a high degree of data structure.   For that 
  8.         reason,  it  would probably be to your advantage to  lightly 
  9.         skim over these topics and come back to them later when  you 
  10.         have  a  substantial base of Pascal programming  experience.  
  11.         It would be good to at least skim over this material  rather 
  12.         than  completely neglecting it,  so you will have an idea of 
  13.         how  pointers and dynamic allocation work and that they  are 
  14.         available for your use when needed.
  15.  
  16.             A  complete understanding of this material will  require 
  17.         deep  concentration  as it is very complex and  not  at  all 
  18.         intuitive.   Nevertheless,  if you pay close attention,  you 
  19.         will have a good grasp of pointers and dynamic allocation in 
  20.         a short time.
  21.  
  22.                 WHAT ARE POINTERS, AND WHAT GOOD ARE THEY?
  23.  
  24.             If  you  examine POINTERS,  you will see a very  trivial 
  25.         example  of  pointers and how they are  used.   In  the  VAR 
  26.         declaration, you will see that the two variables have a ^ in 
  27.         front  of  their respective types.   These are not  actually 
  28.         variables,  instead,  they  point to  dynamically  allocated 
  29.         variables  that  have  not been defined yet,  and  they  are 
  30.         called pointers.
  31.  
  32.             The  pointer  "my_name" is a pointer to a  20  character 
  33.         string  and is therefore not a variable into which  a  value 
  34.         can be stored.   This is a very special Pascal TYPE,  and it 
  35.         cannot be assigned a character string,  only a pointer value 
  36.         or  address.   The  pointer  actually points to  an  address 
  37.         somewhere  within the computer memory,  and can  access  the 
  38.         data stored at that address.
  39.  
  40.             Your computer has some amount of memory installed in it. 
  41.         If it is an IBM-PC or compatible,  it can have up to 640K of 
  42.         RAM which is addressable by various programs.  The operating 
  43.         system requires about 60K of the total, and if you are using 
  44.         TURBO  Pascal  it  requires about  35K.   The  TURBO  Pascal 
  45.         program  can  use  up to 64K.   Adding those  three  numbers 
  46.         together  results  in  about  159K.   Any  memory  you  have 
  47.         installed  in excess of that is available for the stack  and 
  48.         the  heap.    The  stack  is  a  standard  DOS  defined  and 
  49.         controlled  area that can grow and shrink as  needed.   Many 
  50.         books  are  available  to  define  the  stack  if  you   are 
  51.         interested in more information on it.
  52.  
  53.  
  54.  
  55.  
  56.  
  57.                                  Page 60
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.               CHAPTER 12 - Pointers and Dynamic Allocation
  68.  
  69.  
  70.             The  heap  is  a  Pascal defined  entity  that  utilizes 
  71.         otherwise   unused  memory  to  store   data.    It   begins 
  72.         immediately  following  the program and grows  as  necessary 
  73.         upward toward the stack which is growing downward.   As long 
  74.         as they never meet,  there is no problem.   If they meet,  a 
  75.         run-time error is generated.   The heap is therefore outside 
  76.         of  the 64K limitation of TURBO Pascal and many other Pascal 
  77.         compilers.
  78.  
  79.             If you did not understand the last two paragraphs, don't 
  80.         worry.  Simply remember that dynamically allocated variables 
  81.         are  stored  on  the  heap  and do  not  count  in  the  64K 
  82.         limitation placed upon you by some compilers.
  83.  
  84.             Back to our example program, POINTERS.  When we actually 
  85.         begin executing the program,  we still have not defined  the 
  86.         variables  we  wish  to use to store  data  in.   The  first 
  87.         executable  statement  generates a variable for us  with  no 
  88.         name  and stores it on the heap.   Since it has no name,  we 
  89.         cannot do anything with it,  except for the fact that we  do 
  90.         have  a pointer "my_name" that is pointing to it.   By using 
  91.         the pointer, we can store up to 20 characters in it, because 
  92.         that is its type, and later go back and retrieve it.
  93.  
  94.                         WHAT IS DYNAMIC ALLOCATION?
  95.  
  96.             The  variable  we have just described is  a  dynamically 
  97.         allocated  variable  because  it was not defined  in  a  VAR 
  98.         declaration,   but  with  a  "new"  procedure.    The  "new" 
  99.         procedure  creates  a variable of the type  defined  by  the 
  100.         pointer,  puts  it  on  the heap,  and finally  assigns  the 
  101.         address  of  the  variable  to  the  pointer  itself.   Thus 
  102.         "my_name"  contains the address of the  variable  generated.  
  103.         The variable itself is referenced by using the pointer to it 
  104.         followed  by a ^,  and is read,  "the variable to which  the 
  105.         pointer points".
  106.  
  107.             The  next  statement assigns a place on the heap  to  an 
  108.         INTEGER  type  variable  and puts its address  in  "my_age".  
  109.         Following  the  "new"  statements  we  have  two  assignment 
  110.         statements  in  which  the  two  variables  pointed  at  are 
  111.         assigned values compatible with their respective types,  and 
  112.         they  are both written out to the video display.   The  last 
  113.         two statements are illustrations of the way the  dynamically 
  114.         allocated variables are removed from use.   When they are no 
  115.         longer  needed,  they  are  disposed of with  the  "dispose" 
  116.         procedure.
  117.  
  118.             In   such   a  simple  program,   pointers   cannot   be 
  119.         appreciated,  but it is necessary for a simple illustration.  
  120.         In a large,  very active program,  it is possible to  define 
  121.  
  122.  
  123.                                  Page 61
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.               CHAPTER 12 - Pointers and Dynamic Allocation
  134.  
  135.  
  136.         many variables,  dispose of some of them,  define more,  and 
  137.         dispose of more, etc.  Each time some variables are disposed 
  138.         of,  their  space  is  then made  available  for  additional 
  139.         variables defined with the "new" procedure.
  140.  
  141.             The  heap can be made up of any assortment of variables, 
  142.         they  do  not have to all be the same.   One thing  must  be 
  143.         remembered,  anytime a variable is defined,  it will have  a 
  144.         pointer  pointing to it.   The pointer is the only means  by 
  145.         which  the variable can be accessed.   If the pointer to the 
  146.         variable is lost or changed, the data itself is lost for all 
  147.         practical purposes.
  148.  
  149.                        DYNAMICALLY STORING RECORDS;
  150.  
  151.             The next example program,  DYNREC, is a repeat of one we 
  152.         studied  in an earlier chapter.   For your own  edification, 
  153.         review the example program BIGREC before going ahead in this 
  154.         chapter.   Assuming  that you are back in DYNREC,  you  will 
  155.         notice  that this program looks very similar to the  earlier 
  156.         one,  and in fact they do exactly the same thing.   The only 
  157.         difference  in  the TYPE declaration is the  addition  of  a 
  158.         pointer "person_id",  and in the VAR declaration,  the first 
  159.         four  variables  are  defined as  pointers  here,  and  were 
  160.         defined as record variables in the last program.
  161.  
  162.                   WE JUST BROKE THE GREAT RULE OF PASCAL
  163.  
  164.             Notice   in  the  TYPE  declaration  that  we  used  the 
  165.         identifier "person" before we defined it,  which is  illegal 
  166.         to  do in Pascal.   Foreseeing the need to define a  pointer 
  167.         prior  to  the record,  the designers of Pascal allow us  to 
  168.         break  the rule in this one place.   The pointer could  have 
  169.         been defined after the record in this case,  but it was more 
  170.         convenient  to  put  it before,  and  in  the  next  example 
  171.         program,  it  will be required to put it before the  record.  
  172.         We will get there soon.
  173.  
  174.             Since  "friend"  is  really 50  pointers,  we  have  now 
  175.         defined  53 different pointers to records,  but so far  have 
  176.         defined  no  variables other than "temp"  and  "index".   We 
  177.         immediately define a record with "self" pointing to it,  and 
  178.         use  the  pointer  so defined to fill  the  record  defined.  
  179.         Compare  this  to  "BIGREC"  and you will  see  that  it  is 
  180.         identical  except  for the addition of the "new" and  adding 
  181.         the  ^  to  each use of the pointer to  designate  the  data 
  182.         pointed to.
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189.                                  Page 62
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.               CHAPTER 12 - Pointers and Dynamic Allocation
  200.  
  201.  
  202.                         THIS IS A TRICK, BE CAREFUL
  203.  
  204.             Now  go down to the place where "mother" is  assigned  a 
  205.         record and is then pointing to the record.  It seems an easy 
  206.         +thing to do then to simply assign all of the values of self 
  207.         to  all the values of mother as shown in the next statement, 
  208.         but it doesn't work.   All the statement does,  is make  the 
  209.         pointer  "mother"  point to the same place where  "self"  is 
  210.         pointing.   The  data  that  was allocated  to  the  pointer 
  211.         "mother"  is  now somewhere on the heap,  but we don't  know 
  212.         where, so we cannot find it, use it, or deallocate it.  This 
  213.         is an example of losing data on the heap.  The proper way is 
  214.         given  in  the  next  two statements  where  all  fields  of 
  215.         "father"  are  defined by all fields of  "mother"  which  is 
  216.         pointing  at  the original "self" record.   Note that  since 
  217.         "mother"  and "self" are both pointing at the  same  record, 
  218.         changing  the  data with either pointer results in the  data 
  219.         appearing to be changed in both because there is,  in  fact, 
  220.         only one field.
  221.  
  222.             In  order  to  WRITE  from or READ  into  a  dynamically 
  223.         assigned  record it is necessary to use a  temporary  record 
  224.         since  dynamically  assigned records are not allowed  to  be 
  225.         used in I/O statements.   This is illustrated in the section 
  226.         of the program that writes some data to the monitor.
  227.  
  228.             Finally,   the   dynamically  allocated  variables   are 
  229.         disposed  of  prior  to ending the program.   For  a  simple 
  230.         program such as this, it is not necessary to dispose of them 
  231.         because all dynamic variables are disposed of  automatically 
  232.         when  the  program  is  terminated.    Notice  that  if  the 
  233.         "dispose(mother)" statement was included in the program, the 
  234.         data  could  not be found due to the lost pointer,  and  the 
  235.         program would be unpredictable, probably leading to a system 
  236.         crash.
  237.  
  238.                        SO WHAT GOOD IS THIS ANYWAY?
  239.  
  240.             Remember  when  you were initially studying  BIGREC?   I 
  241.         suggested  that you see how big you could make the  constant 
  242.         "number_of_friends" before you ran out of memory.   At  that 
  243.         time  we  found that it could be made slightly greater  than 
  244.         1000   before  we  got  the  memory  overflow   message   at 
  245.         compilation.  Try the same thing with DYNREC to see how many 
  246.         records  it  can handle,  remembering that the  records  are 
  247.         created dynamically,  so you will have to run the program to 
  248.         actually run out of memory.  The final result will depend on 
  249.         how  much  memory you have installed,  and how  many  memory 
  250.         resident programs you are using such as "Sidekick".   If you 
  251.         have  a  full  memory of 640K,  I would  suggest  you  start 
  252.         somewhere above 8000 records of "friend".
  253.  
  254.  
  255.                                  Page 63
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.               CHAPTER 12 - Pointers and Dynamic Allocation
  266.  
  267.  
  268.  
  269.             Now   you  should  have  a  good  idea  of  why  Dynamic 
  270.         Allocation can be used to greatly increase the usefulness of 
  271.         your programs.   There is, however, one more important topic 
  272.         we  must cover on dynamic allocation.   That is  the  linked 
  273.         list.
  274.  
  275.                           WHAT IS A LINKED LIST?
  276.  
  277.             Understanding and using a linked list is by far the most 
  278.         baffling  topic  you will confront in Pascal.   Many  people 
  279.         simply  throw up their hands and never try to use  a  linked 
  280.         list.   I  will  try to help you understand it by use of  an 
  281.         example  and  lots  of  explanation.   Examine  the  program 
  282.         LINKLIST for an example of a linked list.   I tried to  keep 
  283.         it  short  so you could see the entire operation and yet  do 
  284.         something meaningful.
  285.  
  286.             To begin with,  notice that there are two TYPEs defined, 
  287.         a pointer to the record and the record itself.   The record, 
  288.         however,  has one thing about it that is new to us, the last 
  289.         entry, "next" is a pointer to this very record.  This record 
  290.         then,  has  the ability to point to itself,  which would  be 
  291.         trivial  and meaningless,  or to another record of the  same 
  292.         type  which  would be extremely useful in  some  cases.   In 
  293.         fact,  this is the way a linked list is used.   I must point 
  294.         out, that the pointer to another record, in this case called 
  295.         "next",  does  not have to be last in the list,  it  can  be 
  296.         anywhere it is convenient for you.
  297.  
  298.             A couple of pages ago, we discussed the fact that we had 
  299.         to  break  the  great rule of Pascal and use  an  identifier 
  300.         before it was defined.   This is the reason the exception to 
  301.         the  rule  was allowed.   Since the pointer  points  to  the 
  302.         record,  and the record contains a reference to the pointer, 
  303.         one  has  to be defined after being used,  and by  rules  of 
  304.         Pascal,  the pointer can be defined first, provided that the 
  305.         record  is  defined  immediately following it.   That  is  a 
  306.         mouthful  but  if  you  just use the  syntax  shown  in  the 
  307.         example, you will not get into trouble with it.
  308.  
  309.                             STILL NO VARIABLES?
  310.  
  311.             It may seem strange, but we still will have no variables 
  312.         defined,  except  for our old friend "index".   In fact  for 
  313.         this example,  we will only define 3 pointers.   In the last 
  314.         example  we  defined 54 pointers,  and had lots  of  storage 
  315.         room.  Before we are finished, we will have at least a dozen 
  316.         pointers but they will be stored in our records, so they too 
  317.         will be dynamically allocated.
  318.  
  319.  
  320.  
  321.                                  Page 64
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.               CHAPTER 12 - Pointers and Dynamic Allocation
  332.  
  333.  
  334.             Lets look at the program itself now.  First, we create a 
  335.         dynamically  allocated record and define it by  the  pointer 
  336.         "place_in_list".   It  is composed of the three data fields, 
  337.         and another pointer.   We define "start_of_list" to point to 
  338.         the  first record created,  and we will leave  it  unchanged 
  339.         throughout  the program.   The pointer "start_of_list"  will 
  340.         always point to the first record in the linked list which we 
  341.         are building up.
  342.  
  343.             We  define  the three variables in the record to be  any 
  344.         name  we  desire  for illustrative  purposes,  and  set  the 
  345.         pointer in the record to NIL.   NIL is a reserved word  that 
  346.         doesn't  put  an  address in the pointer but defines  it  as 
  347.         empty.  A pointer that is currently NIL cannot be written to 
  348.         the  display as it has no value,  but it can be tested in  a 
  349.         logical  statement to see if it is NIL.   It is therefore  a 
  350.         dummy  assignment.   With all of that,  the first record  is 
  351.         completely defined.
  352.  
  353.                         DEFINING THE SECOND RECORD
  354.  
  355.              When  you  were young you may have played  a  searching 
  356.         game  in which you were given a clue telling you  where  the 
  357.         next clue was at.   The next clue had a clue to the location 
  358.         of  the third clue.   You kept going from clue to clue until 
  359.         you  found the prize.   You simply exercised a linked  list.  
  360.         We  will now build up the same kind of a list in which  each 
  361.         record will tell us where the next record is at.
  362.  
  363.             We will now define the second record.   Our goal will be 
  364.         to store a pointer to the second record in the pointer field 
  365.         of  the first record.   In order to keep track of  the  last 
  366.         record,  the one in which we need to update the pointer,  we 
  367.         will  keep  a  pointer to it in "temp_place".   Now  we  can 
  368.         create another "new" record and use "place_in_list" to point 
  369.         to  it.   Since  "temp_place" is now pointing at  the  first 
  370.         record,  we  can  use it to store the value of  the  pointer 
  371.         which  points to the new record.   The 3 data fields of  the 
  372.         new record are assigned nonsense data for our  illustration, 
  373.         and the pointer field of the new record is assigned NIL.
  374.  
  375.             Lets review our progress to this point.  We now have the 
  376.         first record with a name and a pointer to the second record, 
  377.         and  a  second  record with a different name and  a  pointer 
  378.         assigned NIL.   We also have three pointers, one pointing to 
  379.         the first record,  one pointing to the last record,  and one 
  380.         we  used  just  to get here since it  is  only  a  temporary 
  381.         pointer.   If you understand what is happening so far,  lets 
  382.         go  on to add some additional records to the list.   If  you 
  383.         are confused, go back over this material again.
  384.  
  385.  
  386.  
  387.                                  Page 65
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.               CHAPTER 12 - Pointers and Dynamic Allocation
  398.  
  399.  
  400.                              TEN MORE RECORDS
  401.  
  402.             The  next section of code is contained within a FOR loop 
  403.         so  the statements are simply repeated ten  times.   If  you 
  404.         observe  carefully,  you will notice that the statements are 
  405.         identical  to the second group of statements in the  program 
  406.         (except of course for the name assigned).   They operate  in 
  407.         exactly  the same manner,  and we end up with ten more names 
  408.         added  to  the list.   You will now see  why  the  temporary 
  409.         pointer was necessary,  but pointers are cheap, so feel free 
  410.         to use them at will. A pointer only uses 4 bytes of memory.
  411.  
  412.             We  now have generated a linked list of twelve  entries.  
  413.         We  have a pointer pointing at the first entry,  and another 
  414.         pointer pointing at the last.   The only data stored  within 
  415.         the program itself are three pointers,  and one integer, all 
  416.         of  the  data is on the heap.   This is one advantage  to  a 
  417.         linked list,  it uses very little internal memory, but it is 
  418.         costly  in  terms of programming.   You should never  use  a 
  419.         linked  list  simply  to save memory,  but  only  because  a 
  420.         certain  program  lends  itself well to  it.   Some  sorting 
  421.         routines are extremely fast because of using a linked  list, 
  422.         and it could be advantageous to use in a database.
  423.  
  424.                       HOW DO WE GET TO THE DATA NOW?
  425.  
  426.             Since  the data is in a list,  how can we get a copy  of 
  427.         the  fourth entry for example?   The only way is to start at 
  428.         the beginning of the list and successively examine  pointers 
  429.         until  you  reach the desired one.   Suppose you are at  the 
  430.         fourth and then wish to examine the third.   You cannot back 
  431.         up,  because  you didn't define the list that way,  you  can 
  432.         only  start at the beginning and count to  the  third.   You 
  433.         could  have  defined  the  record  with  two  pointers,  one 
  434.         pointing forward,  and one pointing backward.  This would be 
  435.         a  doubly-linked  list and you could then go  directly  from 
  436.         entry four to entry three.
  437.  
  438.             Now that the list is defined, we will read the data from 
  439.         the  list and display it on the video monitor.   We begin by 
  440.         defining the pointer,  "place_in_list",  as the start of the 
  441.         list.   Now  you see why it was important to keep a copy  of 
  442.         where the list started.   In the same manner as filling  the 
  443.         list,  we  go from record to record until we find the record 
  444.         with NIL as a pointer.
  445.  
  446.             There are entire books on how to use linked  lists,  and 
  447.         most Pascal programmers will seldom, if ever, use them.  For 
  448.         this  reason,  additional detail is considered  unnecessary, 
  449.         but  to be a fully informed Pascal programmer,  some insight 
  450.         is necessary.
  451.  
  452.  
  453.                                  Page 66
  454.  
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.               CHAPTER 12 - Pointers and Dynamic Allocation
  464.  
  465.  
  466.  
  467.                            PROGRAMMING EXERCISE
  468.  
  469.         1.  Write  a program to store a few names dynamically,  then 
  470.             display  the stored names on the monitor.  As your first 
  471.             exercise in dynamic allocation, keep it very simple.
  472.  
  473.  
  474.  
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.                                  Page 67
  520.  
  521.